#include "stdafx.h"
#include <dbt.h>
#include <Shellapi.h>
#include <Shlwapi.h>
#include <Strsafe.h>
#include "Device.h"
#include "Dialog.h"
#include "Notify.h"
#include "Registry.h"
#include "Setup.h"
#include "String.h"
#include "UpgraApp.h"
#include "Xync.h"

#pragma comment(lib,"Shlwapi.lib")

#define	WM_NOTIFYICON	(WM_USER+1)
#define	WM_UPGRADE		(WM_USER+2)

class Xync:public Dialog{
public:
	static void	run(HINSTANCE);
	static TCHAR	appName[];
	static TCHAR	upgrade[];
	static TCHAR	noupgrade[];

private:
	static void	browse		(void);
	static void	uniqueness	(void);

	uint	autoRun1,autoRun2;
	HCURSOR	cursor;
	HMENU	menu;
	Notify*	notify;

	Xync(HINSTANCE hinst);

	PTSTR	className		(void);
	LRESULT onCommand		(WPARAM,LPARAM);
	LRESULT onDeviceChange	(WPARAM,LPARAM);
	BOOL	onInitDialog	(LPARAM);
	LRESULT	onNotifyIcon	(WPARAM,LPARAM);
	LRESULT onUser			(uint,WPARAM,LPARAM);
	void	set				(void);
};

TCHAR	Xync::appName[]=L"XYNC";
TCHAR	Xync::noupgrade[]=L"-upgraded";
TCHAR	Xync::upgrade[]=L"-install";

Xync::Xync(HINSTANCE instance){
	inst=instance;
	registerClass();
	create(MAKEINTRESOURCE(IDD_ABOUTBOX),0);
};

void Xync::browse(void){
	TCHAR o[MAX_PATH];
	String *s;
	StringCchCopy(o,MAX_PATH,L"http://");
	try{
		MachineOrUser reg(L"Software\\Phoxell\\xync");
		s=reg.get(L"host",L"www.phoxell.com");
	}catch(int){
		s=new String(L"www.phoxell.com");
	}
	StringCchCat(o,MAX_PATH,s->Ptstr());
	StringCchCat(o,MAX_PATH,L"/");
	PTSTR t=Device::serialNumber();
	if(t){
		StringCchCat(o,MAX_PATH,L"kalkr/");
		StringCchCat(o,MAX_PATH,t);
	}
	ShellExecute(0,L"open",o,0,0,SW_SHOW);
}
PTSTR Xync::className(void){
	return appName;
}
LRESULT Xync::onCommand(WPARAM wparam,LPARAM lparam){
	switch(LOWORD(wparam)){
	case IDOK:
	case IDCANCEL:
		set();
		hide();
		break;
	case IDC_RUN:
		autoRun1=isButtonChecked(IDC_RUN)==BST_CHECKED;
		set();
		break;
	case IDM_ABOUT:
		show();
		break;
	case IDM_EXIT:
		PostQuitMessage(0);
		break;
	case IDM_WEBSITE:
		browse();
		break;
	default:
		return FALSE;
	}
	return TRUE;
}
LRESULT Xync::onDeviceChange(WPARAM wparam,LPARAM lparam){
	switch(wparam){
	case DBT_DEVICEREMOVECOMPLETE:
		Device::closeAll();
		break;
	case DBT_DEVNODES_CHANGED:
		Device::closeAll();
	case DBT_DEVICEARRIVAL:
		Device::openAll();
		break;
	default:
		return 1;
	}
	return 0;
}
BOOL Xync::onInitDialog(LPARAM lparam){
	checkButton(IDC_RUN,autoRun1?BST_CHECKED:BST_UNCHECKED);
	return TRUE;
}
LRESULT Xync::onNotifyIcon(WPARAM id,LPARAM mouseMessage){
	switch(mouseMessage){
	case WM_LBUTTONUP:
		browse();
		break;
	case WM_RBUTTONUP:
		POINT p;
		GetCursorPos(&p);
		TrackPopupMenu(GetSubMenu(menu,0),TPM_LEFTALIGN|TPM_TOPALIGN,
			p.x,p.y,0,hwnd,NULL);
		break;
	}
	return 1;
}
LRESULT Xync::onUser(uint message,WPARAM wparam,LPARAM lparam){
	switch(message){
	case WM_NOTIFYICON:
		return onNotifyIcon(wparam,lparam);
	case WM_UPGRADE:
		PostQuitMessage(0);
		break;
	}
	return 0;
}
void Xync::run(HINSTANCE instance){
	uniqueness();
	HICON icon=LoadIcon(instance,MAKEINTRESOURCE(IDI_FOXYNC));
	Xync x(instance);
	x.autoRun1=1;
	x.menu=LoadMenu(instance,MAKEINTRESOURCE(IDC_FOXYNC));
	x.cursor=LoadCursor(0,IDC_ARROW);
	x.notify=new Notify(&x,1,WM_NOTIFYICON,icon);
	Device::openAll();
	x.autoRun2=Setup::check(appName);
	if(!x.autoRun2)
		x.show();
	x.messageLoop();
	Device::closeAll();
	delete x.notify;
	x.set();
}
void Xync::set(void){
	if(autoRun1!=autoRun2){
		Setup::set(appName,autoRun1);
		autoRun2=autoRun1;
	}
}
void Xync::uniqueness(void){
	HANDLE mutex=CreateMutex(NULL,FALSE,appName);
	if(mutex!=NULL){
		if(GetLastError()!=ERROR_ALREADY_EXISTS)
			return;
	}
	ExitProcess(0);
}
int APIENTRY _tWinMain(HINSTANCE instance,HINSTANCE prevInstance,
	LPTSTR cmdLine,int cmdShow){
	PTSTR cmd=GetCommandLine();
	ubyte nu=0,up=0;
	if(cmd=wcsrchr(cmd,L'-')){
		if(!StrCmp(cmd,Xync::noupgrade))
			nu=1;
		else if(!StrCmp(cmd,Xync::upgrade))
			up=1;
	}
	if(up){
		UpgraApp::setup(Xync::appName,WM_UPGRADE,Xync::noupgrade);
		return 0;
	}
	//if(!nu)
	//	UpgraApp::begin(Xync::upgrade);
	Xync::run(instance);
	UpgraApp::end();
	return 0;
}